package cn.lili.modules.kit.plugin.wechat;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.lili.cache.Cache;
import cn.lili.cache.CachePrefix;
import cn.lili.common.context.ThreadContextHolder;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.event.TransactionCommitSendMQEvent;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.utils.CurrencyUtil;
import cn.lili.common.utils.GsonUtils;
import cn.lili.common.utils.SnowFlake;
import cn.lili.exchange.AmqpExchangeProperties;
import cn.lili.modules.kit.core.PaymentHttpResponse;
import cn.lili.modules.kit.core.enums.RequestMethodEnums;
import cn.lili.modules.kit.core.kit.*;
import cn.lili.modules.kit.plugin.wechat.model.*;
import cn.lili.modules.member.client.VipClient;
import cn.lili.modules.member.client.VipConfigClient;
import cn.lili.modules.order.trade.client.TradeClient;
import cn.lili.modules.payment.entity.dos.CombinePaymentLog;
import cn.lili.modules.payment.entity.dos.PaymentData;
import cn.lili.modules.payment.entity.dos.PaymentLog;
import cn.lili.modules.payment.entity.dos.SubMerchantInformation;
import cn.lili.modules.payment.entity.dto.*;
import cn.lili.modules.payment.entity.enums.PaymentClientEnum;
import cn.lili.modules.payment.entity.enums.PaymentMethodEnum;
import cn.lili.modules.payment.entity.enums.PaymentSceneEnums;
import cn.lili.modules.payment.service.*;
import cn.lili.modules.payment.wechat.enums.WechatApiEnum;
import cn.lili.modules.payment.wechat.enums.WechatDomain;
import cn.lili.modules.system.client.SettingClient;
import cn.lili.modules.system.entity.dos.LiVipConfig;
import cn.lili.modules.system.entity.dos.Setting;
import cn.lili.modules.system.entity.dto.DistributionSetting;
import cn.lili.modules.system.entity.dto.UrbanSubstationAuditSetting;
import cn.lili.modules.system.entity.dto.payment.WechatPaymentSetting;
import cn.lili.modules.system.entity.enums.SettingEnum;
import cn.lili.routing.PaymentRoutingKey;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Component
@Slf4j
public class WechatPluginNewManage {

    @Resource
    private Cache<String> cache;
    @Resource
    private SettingClient settingClient;
    @Resource
    private PaymentLogService paymentLogService;
    @Resource
    private ApplicationEventPublisher applicationEventPublisher;
    @Resource
    private AmqpExchangeProperties amqpExchangeProperties;
    @Resource
    private CombinePaymentLogService combinePaymentLogService;
    @Resource
    private TradeClient tradeClient;

    @Resource
    private VipConfigClient vipConfigClient;

    @Resource
    private VipClient vipClient;

    @Resource
    private SupplierAuditService supplierAuditService;

    @Resource
    private PaymentDataService paymentDataService;

    /**
     * H5微信支付
     *
     * @param notifyUrl 回调地址
     */
    public PaymentHttpResponse wechatPay(PaymentWakeupParam paymentWakeupParam, String notifyUrl, WechatApiEnum wechatApiEnum) {
        WechatPaymentSetting setting = wechatPaymentSetting();

        // 支付参数
        PayParam payParam = paymentWakeupParam.getPayParam();

        TransactionsRequest request = new TransactionsRequest();
        request.setAppid(setting.getAppId());
        request.setMchid(setting.getMchId());
        request.setOutTradeNo(SnowFlake.getIdStr());
        request.setDescription(payParam.getTitle());
        request.setNotifyUrl(notifyUrl);

        PartnerTransactionsRequest.Amount amount = new PartnerTransactionsRequest.Amount();
        amount.setTotal(CurrencyUtil.fen(payParam.getTotalAmount()));
        request.setAmount(amount);

        PartnerTransactionsRequest.SceneInfo sceneInfo = new PartnerTransactionsRequest.SceneInfo();
        sceneInfo.setPayerClientIp(IpKit.getRealIp(ThreadContextHolder.getHttpRequest()));
        request.setSceneInfo(sceneInfo);

        // 如果需要支付人OPENID
        if (paymentWakeupParam.getPayParam().getPaymentClientEnum().equals(PaymentClientEnum.JSAPI) || paymentWakeupParam.getPayParam().getPaymentClientEnum().equals(PaymentClientEnum.MP)) {
            PartnerTransactionsRequest.Payer payer = new PartnerTransactionsRequest.Payer();
            //如果需要openid却没传递，则抛出异常
            if (CharSequenceUtil.isEmpty(paymentWakeupParam.getPayParam().getOpenid())) {
                throw new ServiceException(ResultCode.PAY_ERROR, "支付参数错误，缺少openid");
            }
            payer.setSpOpenid(paymentWakeupParam.getPayParam().getOpenid());
            request.setPayer(payer);
        }
        log.info("统一下单请求 {}", GsonUtils.toJson(request));

        //支付日志对象
        PaymentLog paymentLog = paymentWakeupParam.getPaymentLog();
        paymentLog.setMchId(setting.getAppId());
        paymentLog.setOutTradeNo(request.getOutTradeNo());

        PaymentHttpResponse response = null;
        try {
            response = WechatApi.v3(RequestMethodEnums.POST, WechatDomain.CHINA.toString(), wechatApiEnum.toString(), setting.getMchId(), setting.getSerialNumber(), null, setting.getApiclient_key(), GsonUtils.toJson(request));
            PaymentData paymentData = new PaymentData();
            paymentData.setOrderSn(paymentWakeupParam.getOrderSn());
            paymentData.setPayType(1);
            paymentData.setSendBody(GsonUtils.toJson(request));
            paymentData.setResBody(com.alibaba.fastjson.JSONObject.toJSONString(response));
            paymentDataService.save(paymentData);
            log.info("paymentData save data == {}", com.alibaba.fastjson.JSONObject.toJSONString(paymentData));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return response;
    }

    /**
     * H5微信支付
     *
     * @param notifyUrl 回调地址
     */
    public PaymentHttpResponse wechatPay2(PaymentWakeupParam paymentWakeupParam, String notifyUrl, WechatApiEnum wechatApiEnum) {
        WechatPaymentSetting setting = wechatPaymentSetting();

        // 支付参数
        PayParam payParam = paymentWakeupParam.getPayParam();

        TransactionsRequest request = new TransactionsRequest();
        request.setAppid(setting.getAppId());
        request.setMchid(setting.getMchId());
        request.setOutTradeNo(paymentWakeupParam.getCombinePaymentLog().getCombineOutTradeNo());
        request.setDescription(payParam.getTitle());
        request.setNotifyUrl(notifyUrl);

        PartnerTransactionsRequest.Amount amount = new PartnerTransactionsRequest.Amount();
        amount.setTotal(CurrencyUtil.fen(payParam.getTotalAmount()));
        request.setAmount(amount);

        PartnerTransactionsRequest.SceneInfo sceneInfo = new PartnerTransactionsRequest.SceneInfo();
        sceneInfo.setPayerClientIp(IpKit.getRealIp(ThreadContextHolder.getHttpRequest()));
        request.setSceneInfo(sceneInfo);
        request.setAttach("{\"isCombine\":\"200\"}");

        // 如果需要支付人OPENID
        if (paymentWakeupParam.getPayParam().getPaymentClientEnum().equals(PaymentClientEnum.JSAPI) || paymentWakeupParam.getPayParam().getPaymentClientEnum().equals(PaymentClientEnum.MP)) {
            PartnerTransactionsRequest.Payer payer = new PartnerTransactionsRequest.Payer();
            //如果需要openid却没传递，则抛出异常
            if (CharSequenceUtil.isEmpty(paymentWakeupParam.getPayParam().getOpenid())) {
                throw new ServiceException(ResultCode.PAY_ERROR, "支付参数错误，缺少openid");
            }
            payer.setSpOpenid(paymentWakeupParam.getPayParam().getOpenid());
            request.setPayer(payer);
        }
        log.info("统一下单请求 {}", GsonUtils.toJson(request));

        //支付日志对象

        PaymentHttpResponse response = null;
        try {
            response = WechatApi.v3(RequestMethodEnums.POST, WechatDomain.CHINA.toString(), wechatApiEnum.toString(), setting.getMchId(), setting.getSerialNumber(), null, setting.getApiclient_key(), GsonUtils.toJson(request));
            PaymentData paymentData = new PaymentData();
            paymentData.setOrderSn(paymentWakeupParam.getOrderSn());
            paymentData.setPayType(1);
            paymentData.setSendBody(GsonUtils.toJson(request));
            paymentData.setResBody(com.alibaba.fastjson.JSONObject.toJSONString(response));
            log.info("paymentData save data == {}", com.alibaba.fastjson.JSONObject.toJSONString(paymentData));
            paymentDataService.save(paymentData);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return response;
    }

    /**
     * H5微信支付 合单
     *
     * @param notifyUrl 回调地址
     */
    public PaymentHttpResponse mergeWechatPay(PaymentWakeupParam paymentWakeupParam, String notifyUrl, WechatApiEnum wechatApiEnum) {
        WechatPaymentSetting setting = wechatPaymentSetting();
        //附加数据
        String attach = JSONUtil.toJsonStr(new ThirdPayCallbackParam(paymentWakeupParam.getPayParam()));

        //合单支付请求参数
        CombineTransactionsRequest request = new CombineTransactionsRequest();
        request.setCombineAppid(setting.getAppId());
        request.setCombineMchid(setting.getMchId());
        request.setCombineOutTradeNo(SnowFlake.getIdStr());
        request.setNotifyUrl(notifyUrl);

        // 如果需要支付人OPENID
        if (paymentWakeupParam.getPayParam().getPaymentClientEnum().equals(PaymentClientEnum.JSAPI) || paymentWakeupParam.getPayParam().getPaymentClientEnum().equals(PaymentClientEnum.MP)) {
            CombineTransactionsRequest.CombinePayerInfo payerInfo = new CombineTransactionsRequest.CombinePayerInfo();
            //如果需要openid却没传递，则抛出异常
            if (CharSequenceUtil.isEmpty(paymentWakeupParam.getPayParam().getOpenid())) {
                throw new ServiceException(ResultCode.PAY_ERROR, "支付参数错误，缺少openid");
            }
            payerInfo.setOpenid(paymentWakeupParam.getPayParam().getOpenid());
            request.setCombinePayerInfo(payerInfo);
        }

        CombineTransactionsRequest.SceneInfo sceneInfo = new CombineTransactionsRequest.SceneInfo();
        sceneInfo.setPayerClientIp(IpKit.getRealIp(ThreadContextHolder.getHttpRequest()));
        sceneInfo.setDeviceId("013467007045764");
        request.setSceneInfo(sceneInfo);

        // 循环子订单
        for (PayParamItem paramItem : paymentWakeupParam.getPayParam().getPayParamItems()) {
            //构建金额信息
            CombineTransactionsRequest.Amount requestAmount = new CombineTransactionsRequest.Amount();
            //设置币种信息
            requestAmount.setCurrency("CNY");
            //设置金额
            requestAmount.setTotalAmount(CurrencyUtil.fen(paramItem.getPrice()));
            CombineTransactionsRequest.SubOrders subOrders = new CombineTransactionsRequest.SubOrders();

            subOrders.setMchid(setting.getMchId());
            //设置 子单商户号  mchId 和 combine_mchId 取值一样
            //如果是特殊订单，则使用平台子商户号，否则使用店铺商户号
            subOrders.setAttach(attach);
            subOrders.setOutTradeNo(SnowFlake.getIdStr());
            subOrders.setDescription(paramItem.getDescription());
            subOrders.setAmount(requestAmount);
            CombineTransactionsRequest.SettleInfo settleInfo = new CombineTransactionsRequest.SettleInfo();
            settleInfo.setProfitSharing(false);
            subOrders.setSettleInfo(settleInfo);
            request.addSubOrders(subOrders);

            //填充第三方流水
            paramItem.setOutTradeNo(subOrders.getOutTradeNo());

        }

        log.info("统一下单请求 {}", JSONUtil.toJsonStr(request));

        PaymentHttpResponse response;
        //请求微信支付接口
        try {
            response = WechatApi.v3(RequestMethodEnums.POST, WechatDomain.CHINA.toString(), wechatApiEnum.toString(), setting.getMchId(),
                    setting.getSerialNumber(), null, setting.getApiclient_key(), GsonUtils.toJson(request));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return response;
    }


    /**
     * 合单订单支付回调处理
     * @param plainText
     * */
    @Transactional
    public void publicNotify2(String plainText){
        PartnerTransactionsResult partnerTransactionsResult = GsonUtils.fromJson(plainText, PartnerTransactionsResult.class);
        CombinePaymentLog combinePaymentLog = combinePaymentLogService.getCombinePaymentLogByCombineOutTradeNo(partnerTransactionsResult.getOutTradeNo());

        //校验支付金额
        if(combinePaymentLog.getPrice() * 100 != partnerTransactionsResult.getAmount().getTotal()){
            log.info("paymentLog.getPrice() * 100 = " + combinePaymentLog.getPrice() * 100);
            log.info("partnerTransactionsResult.getAmount().getTotal() = " + partnerTransactionsResult.getAmount().getTotal());
            log.info("微信普通订单---校验金额失败");
            return;
        }
        log.info("微信普通订单---校验金额成功");

        //写入主动查询结果
        combinePaymentLog.setPaymentResponseSource(JSONUtil.toJsonStr(partnerTransactionsResult));

        String paymentResult = partnerTransactionsResult.getTradeState();

        log.info("1");
        //获取子单支付日志
        List<PaymentLog> paymentLogs = paymentLogService.getPaymentLogByCombineOutTradeNo(combinePaymentLog.getCombineOutTradeNo());
        for (int i =0;i<paymentLogs.size();i++) {
            //如果子单支付日志的交易状态为成功
            if (paymentResult.equals("SUCCESS")) {
                paymentLogs.get(i).setTransactionId(partnerTransactionsResult.getTransactionId());
                paymentLogs.get(i).setOutTradeNo(partnerTransactionsResult.getOutTradeNo());
                paymentLogs.get(i).setPrice(CurrencyUtil.div(partnerTransactionsResult.getAmount().getTotal(), 100));
                paymentLogs.get(i).setIsPay(true);
                //标记已检查
                paymentLogs.get(i).setIsCheck(true);
            } else {
                paymentLogs.get(i).setIsCheck(true);
                paymentLogs.get(i).setIsPay(false);
                paymentLogs.get(i).setTransactionId(partnerTransactionsResult.getTransactionId());
                paymentLogs.get(i).setOutTradeNo(partnerTransactionsResult.getOutTradeNo());
                paymentLogs.get(i).setPrice(CurrencyUtil.div(partnerTransactionsResult.getAmount().getTotal(), 100));
            }
        }

        log.info("#publicNotify2# 支付回调 2");
        paymentLogService.updateBatchById(paymentLogs);
        combinePaymentLogService.updateById(combinePaymentLog);

        log.info("#publicNotify2# 支付回调 3---{}",paymentLogs.get(0).getIsPay());
        // 支付状态为TRUE才进行通知
        if (paymentLogs.get(0).getIsPay().equals(true)) {
            PaymentCallback paymentCallback = PaymentCallback.builder().paymentLogs(paymentLogs).combinePaymentLog(combinePaymentLog).isCombine(true).build();
            log.info("paymentCallback---{}",paymentCallback);
            log.info("微信支付场景1：{}", paymentLogs.get(0).getPaymentScene());
            if (paymentLogs.get(0).getPaymentScene().equals(PaymentSceneEnums.RECHARGE.name())) {
                log.info("微信进入充值回调1");
                applicationEventPublisher.publishEvent(TransactionCommitSendMQEvent.builder().source("普通支付回调业务").exchange(amqpExchangeProperties.getPayment()).routingKey(PaymentRoutingKey.PAYMENT_CALLBACK).message(paymentCallback).build());
            }else {
                tradeClient.paymentCallback(paymentCallback);
            }

            //applicationEventPublisher.publishEvent(TransactionCommitSendMQEvent.builder().source("合单支付回调业务").exchange(amqpExchangeProperties.getPayment()).routingKey(PaymentRoutingKey.PAYMENT_CALLBACK).message(paymentCallback).build());
        }
    }

    /**
     * 普通订单支付回调处理
     * @param plainText 支付宝反馈信息
     * */
    @Transactional
    public void publicNotify(String plainText){
        PartnerTransactionsResult partnerTransactionsResult = GsonUtils.fromJson(plainText, PartnerTransactionsResult.class);
        PaymentLog paymentLog = paymentLogService.getPaymentLogByOutTradeNo(partnerTransactionsResult.getOutTradeNo());
        //校验支付金额

        if(BigDecimal.valueOf(paymentLog.getPrice()).multiply(BigDecimal.valueOf(100)).compareTo(BigDecimal.valueOf(partnerTransactionsResult.getAmount().getTotal())) != 0){
            log.info("paymentLog.getPrice() * 100 = " + BigDecimal.valueOf(paymentLog.getPrice()).multiply(BigDecimal.valueOf(100)));
            log.info("partnerTransactionsResult.getAmount().getTotal() = " + partnerTransactionsResult.getAmount().getTotal());
            log.info("微信普通订单---校验金额失败");
            return;
        }
        log.info("微信普通订单---校验金额成功");

        //写入主动查询结果
        paymentLog.setPaymentResponseSource(JSONUtil.toJsonStr(partnerTransactionsResult));

        String paymentResult = partnerTransactionsResult.getTradeState();
        //支付成功则写入
        if (paymentResult.equals("SUCCESS")) {
            paymentLog.setTransactionId(partnerTransactionsResult.getTransactionId());
            paymentLog.setOutTradeNo(partnerTransactionsResult.getOutTradeNo());
            paymentLog.setPrice(CurrencyUtil.div(partnerTransactionsResult.getAmount().getTotal(), 100));
            paymentLog.setIsPay(true);
            //标记已检查
            paymentLog.setIsCheck(true);
        }
        //支付中则先返回
        else if (paymentResult.equals("USERPAYING")) {
            //标记需要再次查询
            paymentLog.setIsCheck(false);
            paymentLog.setPaymentResponseSource("交易中，等待回传");

        } else if (paymentResult.equals("CLOSED")) {
            //标记已校验
            paymentLog.setIsCheck(true);
        } else {
            paymentLog.setIsCheck(false);
        }
        paymentLogService.updateById(paymentLog);

        // 支付状态为TRUE才进行通知
        if (paymentLog.getIsPay().equals(true)) {
            PaymentCallback paymentCallback = PaymentCallback.builder().paymentLog(paymentLog).isCombine(false).build();
            log.info("微信支付场景2：{}", paymentLog.getPaymentScene());
            if (paymentLog.getPaymentScene().equals(PaymentSceneEnums.RECHARGE.name())) {
                log.info("微信进入充值回调2");
                applicationEventPublisher.publishEvent(TransactionCommitSendMQEvent.builder().source("普通支付回调业务").exchange(amqpExchangeProperties.getPayment()).routingKey(PaymentRoutingKey.PAYMENT_CALLBACK).message(paymentCallback).build());
            }else {
                tradeClient.paymentCallback(paymentCallback);
            }
        }
    }

    /**
     * 合并订单支付回调处理
     * @param plainText 支付宝反馈信息
     * */
    @Transactional
    public void mergePublicNotify(String plainText){
        //合单支付主动查询结果
        CombineQueryResult combineQueryResult = GsonUtils.fromJson(plainText, CombineQueryResult.class);
        CombinePaymentLog combinePaymentLog = combinePaymentLogService.getCombinePaymentLogByCombineOutTradeNo(combineQueryResult.getCombineOutTradeNo());
        //校验支付金额
        BigDecimal total = new BigDecimal(0);
        for (CombineQueryResult.SubOrders subOrders:combineQueryResult.getSubOrders()) {
            total = total.add(new BigDecimal(subOrders.getAmount().getTotalAmount()));
        }
        log.info("total.doubleValue() " + total.doubleValue());
        if(combinePaymentLog.getPrice() * 100 != total.doubleValue()){
            log.info("combinePaymentLog.getPrice() * 100 = " + combinePaymentLog.getPrice() * 100);
            log.info("total.doubleValue()" + total.doubleValue());
            log.info("微信合并订单---校验金额失败");
            return;
        }
        log.info("微信合并订单---校验金额成功");

        //写入主动查询结果
        combinePaymentLog.setPaymentResponseSource(JSONUtil.toJsonStr(combineQueryResult));

        //判定支付结果状态，如果是已关闭或者已支付，则标记合并支付单已校验
        List<CombineQueryResult.SubOrders> subOrders =
                combineQueryResult.getSubOrders().stream().filter(obj -> obj.getTradeState().equals("CLOSED") || obj.getTradeState().equals(
                        "SUCCESS")).toList();

        //如果子单全部为关闭或者支付成功，则标记合单支付状态为已完成
        if (subOrders.size() == combineQueryResult.getSubOrders().size()) {
            combinePaymentLog.setIsCheck(true);
        } else {
            throw new ServiceException("合单支付状态未完成:" + combineQueryResult.getCombineOutTradeNo());
        }


        //获取子单支付日志
        List<PaymentLog> paymentLogs = paymentLogService.getPaymentLogByCombineOutTradeNo(combinePaymentLog.getCombineOutTradeNo());

        for (PaymentLog paymentLog : paymentLogs) {
            for (CombineQueryResult.SubOrders subOrder : combineQueryResult.getSubOrders()) {


                // 如果子单支付日志的订单号和查询结果的订单号一致
                if (subOrder.getOutTradeNo().equals(paymentLog.getOutTradeNo())) {


                    //如果子单支付日志的交易状态为成功
                    if (subOrder.getTradeState().equals("SUCCESS")) {
                        paymentLog.setIsCheck(true);
                        paymentLog.setIsPay(true);
                        paymentLog.setPrice(CurrencyUtil.reversalFen(subOrder.getAmount().getTotalAmount()));
                        paymentLog.setTransactionId(subOrder.getTransactionId());
                        paymentLog.setOutTradeNo(subOrder.getOutTradeNo());
                    } else {
                        paymentLog.setIsCheck(true);
                        paymentLog.setIsPay(false);
                        paymentLog.setPrice(CurrencyUtil.reversalFen(subOrder.getAmount().getTotalAmount()));
                        paymentLog.setOutTradeNo(subOrder.getOutTradeNo());
                        paymentLog.setTransactionId(subOrder.getTransactionId());
                    }
                }
            }
        }

        paymentLogService.updateBatchById(paymentLogs);
        combinePaymentLogService.updateById(combinePaymentLog);

        // 支付状态为TRUE才进行通知
        if (paymentLogs.get(0).getIsPay().equals(true)) {
            PaymentCallback paymentCallback =
                    PaymentCallback.builder().paymentLogs(paymentLogs).combinePaymentLog(combinePaymentLog).isCombine(true).build();
            //tradeClient.paymentCallback(paymentCallback);
            log.info("合单支付回调业务2");
            applicationEventPublisher.publishEvent(TransactionCommitSendMQEvent.builder().source("合单支付回调业务").exchange(amqpExchangeProperties.getPayment()).routingKey(PaymentRoutingKey.PAYMENT_CALLBACK).message(paymentCallback).build());
        }
    }

    /**
     * 获取微信支付配置
     *
     * @return 微信支付配置
     */
    public WechatPaymentSetting wechatPaymentSetting() {
        try {
            Setting systemSetting = settingClient.get(SettingEnum.WECHAT_PAYMENT.name());
            return JSONUtil.toBean(systemSetting.getSettingValue(), WechatPaymentSetting.class);
        } catch (Exception e) {
            log.error("微信支付暂不支持", e);
            throw new ServiceException(ResultCode.PAY_NOT_SUPPORT);
        }
    }

    /**
     * 获取平台公钥
     *
     * @return 平台公钥
     */
    public X509Certificate getPlatformCert() {
        //获取缓存中的平台公钥，如果有则直接返回，否则去微信请求
        String publicCert = cache.getString(CachePrefix.WECHAT_PLAT_FORM_CERT.getPrefix());
//        if (!CharSequenceUtil.isEmpty(publicCert)) {
//            log.info("cache getCertificate == {}", publicCert);
//            return PayKit.getCertificate(publicCert);
//        }
        //获取平台证书列表
        try {

            WechatPaymentSetting setting = wechatPaymentSetting();
            log.info("setting == {}", com.alibaba.fastjson.JSONObject.toJSONString(setting));

            PaymentHttpResponse response = WechatApi.v3(RequestMethodEnums.GET, WechatDomain.CHINA.toString(), WechatApiEnum.GET_CERTIFICATES.toString(), setting.getMchId(), setting.getSerialNumber(), null, setting.getApiclient_key(), "");
            String body = response.getBody();
            log.info("获取微信平台证书body: {}", body);
            if (response.getStatus() == 200) {
                JSONObject jsonObject = JSONUtil.parseObj(body);
                JSONArray dataArray = jsonObject.getJSONArray("data");
                //默认认为只有一个平台证书
                JSONObject encryptObject = dataArray.getJSONObject(0);
                JSONObject encryptCertificate = encryptObject.getJSONObject("encrypt_certificate");
                String associatedData = encryptCertificate.getStr("associated_data");
                String cipherText = encryptCertificate.getStr("ciphertext");
                String nonce = encryptCertificate.getStr("nonce");
                publicCert = getPlatformCertStr(associatedData, nonce, cipherText);
                log.info("publicCert == {}", publicCert);
                long second = (PayKit.getCertificate(publicCert).getNotAfter().getTime() - System.currentTimeMillis()) / 1000;
                cache.put(CachePrefix.WECHAT_PLAT_FORM_CERT.getPrefix(), publicCert, second);
            } else {
                log.error("证书获取失败：{}", body);
                throw new ServiceException(ResultCode.WECHAT_CERT_ERROR);
            }
            return PayKit.getCertificate(publicCert);
        } catch (ServiceException serviceException) {
            throw serviceException;
        } catch (Exception e) {
            log.error("证书获取失败", e);
        }
        return null;
    }

    /**
     * 获取平台证书缓存的字符串
     * 下列各个密钥参数
     *
     * @param associatedData 密钥参数
     * @param nonce          密钥参数
     * @param cipherText     密钥参数
     * @return platform key
     * @throws GeneralSecurityException 密钥获取异常
     */
    private String getPlatformCertStr(String associatedData, String nonce, String cipherText) throws GeneralSecurityException {


        AesUtil aesUtil = new AesUtil(wechatPaymentSetting().getApiKey3().getBytes(StandardCharsets.UTF_8));
        //平台证书密文解密
        //encrypt_certificate 中的  associated_data nonce  ciphertext
        return aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8), nonce.getBytes(StandardCharsets.UTF_8), cipherText);
    }

    /**
     * 获取通知明文
     *
     * @return 微信通知明文
     * @throws Exception 支付异常
     */
    public String getPlaintext() throws Exception {

        HttpServletRequest request = ThreadContextHolder.getHttpRequest();
        String timestamp = request.getHeader("Wechatpay-Timestamp");
        String nonce = request.getHeader("Wechatpay-Nonce");
        String serialNo = request.getHeader("Wechatpay-Serial");
        String signature = request.getHeader("Wechatpay-Signature");

        log.info("timestamp:{} nonce:{} serialNo:{} signature:{}", timestamp, nonce, serialNo, signature);
        String result = HttpKit.readData(request);
        log.info("微信支付通知密文 {}", result);

        WechatPaymentSetting setting = wechatPaymentSetting();
        //校验服务器端响应¬
        return WxPayKit.verifyNotify(serialNo, result, signature, nonce, timestamp, setting.getApiKey3(), Objects.requireNonNull(getPlatformCert()));
    }
}
